/*
 *  Copyright (C) 2010 glauco
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.balisunrise.application;

import java.util.ArrayList;
import java.util.List;
import java.util.jar.Manifest;
import org.balisunrise.annotation.Menu;
import org.balisunrise.annotation.VisualEntity;
import org.balisunrise.common.ActionMap;

/**
 * Esta classe contém os dados de um arquivo JAR carregado pelo JarLoader.
 *
 * @see org.balisunrise.application.JarLoader
 * @author glauco
 */
public class JarInfo {

    public static final String PROP_VERSION = "VEA-Module-Version";

    /**
     * Lista de classes publicas carregadas do Jar.
     */
    List<Class> classes;

    /**
     * Classes que são tipos de dados que implementam a interface Module.
     * @see Module
     */
    List<Class> modulesClasses;

    /**
     * Classes que são tipos de dados que implementam a interface ActionMap, ou
     * possuem a annotation ActionMap.
     * @see org.balisunrise.common.ActionMap
     * @see org.balisunrise.annotation.ActionMap
     */
    List<Class> eventMapClasses;

    /**
     * Classes que são entidades do sistema.
     */
    List<Class> entityClasses;

    /**
     * Classes que são entidades visuais.
     */
    List<Class> visualEntities;

    /**
     * Classes que possuem ações de Menu.
     */
    List<Class> menus;

    /**
     * Classe do jar que é um ApplicationLoader
     * De todos os módulos carregados, apena um deve possuir um
     * ApplicationLoader, caso mais de um tenha, só será executado o do
     * primeiro módulo.
     */
    Class applicationLoader;

    /**
     * Versão do módulo.
     * lida propriedade do Manifest "<code>VEA-Module-Version</code>"
     * Cuidado: pode ser nulo.
     */
    String version;

    /**
     * Hash do arquivo jar.
     * Pode ser nulo.
     */
    String hash;

    /**
     * Manifest do arquivo jar.
     */
    Manifest mf;

    public JarInfo() {
        classes = new ArrayList<Class>();
        modulesClasses = new ArrayList<Class>();
        eventMapClasses = new ArrayList<Class>();
        entityClasses = new ArrayList<Class>();
        visualEntities = new ArrayList<Class>();
    }



    /**
     * Processa as classes deste JarInfo dividindo os modulos, event maps,
     * applicationLoader e version.
     */
    void processClasses(){

        for (Class c : classes) {
            if (c.isAssignableFrom(Module.class)){
                // add to list
                modulesClasses.add(c);
                continue;
            }
            if (c.isAssignableFrom(ActionMap.class)){
                // add to list
                eventMapClasses.add(c);
                continue;
            }
            if (c.isAssignableFrom(ApplicationLoader.class)){
                // set the app...
                applicationLoader = c;
            }
            if (c.isAnnotationPresent(org.balisunrise.annotation.ActionMap.class)){
                // add to list
                eventMapClasses.add(c);
            }
            if (c.isAnnotationPresent(VisualEntity.class)){
                // add to list
                visualEntities.add(c);
            }
            if (c.isAnnotationPresent(Menu.class)){
                // add to list
                menus.add(c);
            }
        }

        if(mf != null){
            java.util.jar.Attributes a = mf.getAttributes(PROP_VERSION);
            // TODO: read the Version 
        }
    }

    /**
     * Processa as classes deste JarInfo em busca das Entities Classes.
     * @param annotationClass Annotation que defini uma Entidade.
     */
    public void processEntities(Class annotationClass){
        entityClasses = new ArrayList<Class>();
        for (Class c : classes) {
            if(c.isAnnotationPresent(annotationClass))
                entityClasses.add(c);
        }
    }

    public Class getApplicationLoader() {
        return applicationLoader;
    }

    public List<Class> getClasses() {
        return classes;
    }

    public List<Class> getEntityClasses() {
        return entityClasses;
    }

    public List<Class> getEventMapClasses() {
        return eventMapClasses;
    }

    public Manifest getMf() {
        return mf;
    }

    public List<Class> getModulesClasses() {
        return modulesClasses;
    }

    public String getVersion() {
        return version;
    }

    public List<Class> getVisualEntities() {
        return visualEntities;
    }

    public List<Class> getMenus() {
        return menus;
    }
}
